package cn.mzcode.recheck.controller;

import cn.mzcode.recheck.entity.RecheckSim;
import cn.mzcode.recheck.resp.ServerResponse;
import cn.mzcode.recheck.service.RecheckService;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author: 马壮
 * @date: 2019/11/21 11:47
 * @description: 自动映射Html路径，支持两级或三级路径
 */
@Slf4j
@Controller
public class ViewController {

    @Autowired
    private RecheckService recheckService;

    @RequestMapping(value = {"/", "index", "home"})
    public String index() {
        log.info("[首页]首页有人访问");
        return "index";
    }

    @PostMapping(value = "/upload")
    @ResponseBody
    public ServerResponse upload(@RequestParam("file") MultipartFile file) {
        log.info("[文件上传]文件上传请求");
        if (file.isEmpty()) {
            return ServerResponse.createByErrorMessage("上传失败，请选择文件");
        }
        try {
            // 保存文件
            String recheckNo = recheckService.saveSrcFile(file);
            log.info("[文件上传]文件上传成功，recheckNo={}", recheckNo);
            // 解压文件
            boolean unzip = recheckService.unzipByRecheckNo(recheckNo);
            log.info("[文件上传]解压文件完成，recheckNo={}，解压结果={}", recheckNo, unzip);
            if (!unzip) {
                return ServerResponse.createByErrorMessage("解压文件失败，压缩文件格式非标准ZIP、RAR或文件完整性已损坏，如文件确认正常，请联系管理员");
            }
            // 检查文件夹结构、文件命名是否符合要求，如不符合，直接删除
            ServerResponse preVerify = recheckService.preVerifyStructure(recheckNo);
            log.info("[文件上传]预检查文件夹结构完成，recheckNo={}，检查结果={}", recheckNo, JSON.toJSONString(preVerify));
            if (!preVerify.isSuccess()) {
                log.info("[文件上传]预检查文件夹结构不通过，清除本次上传文件，recheckNo={}", recheckNo);
                recheckService.cleanFileByRecheckNo(recheckNo);
                return preVerify;
            }
            log.info("[文件上传]调用异步计算，recheckNo={}", recheckNo);
            recheckService.startAsyncCalcSim(recheckNo);
            return ServerResponse.createBySuccess(recheckNo);
        } catch (Exception e) {
            log.error("[文件上传]保存源文件出现异常", e);
            return ServerResponse.createByErrorMessage("上传文件出现异常，请联系管理员");
        }
    }

    @RequestMapping(value = "/upload_ok")
    public String uploadOk(String recheckNo, Model model) {
        if (StringUtils.isEmpty(recheckNo)) {
            return "error/404";
        }
        model.addAttribute("recheckNo", recheckNo);
        return "upload_ok";
    }

    @RequestMapping(value = "/query")
    public String queryResult(String recheckNo, Model model) {
        log.info("[结果查询]查询页面访问");
        if (StringUtils.isNotEmpty(recheckNo)) {
            log.info("[结果查询]查重编号={}", recheckNo);
            boolean complete = recheckService.recheckComplete(recheckNo);
            model.addAttribute("recheckComplete", complete);
            if (complete) {
                List<RecheckSim> recheckSims = recheckService.loadRecheckResult(recheckNo);
                List<List> collect = recheckSims.stream().map(i -> {
                    return Arrays.asList(i.getUser1(), i.getUser2(), Float.valueOf(String.format("%.2f", i.getSim())));
                }).collect(Collectors.toList());
                model.addAttribute("result", JSON.toJSONString(collect));
                model.addAttribute("recheckNo", recheckNo);
                return "query";
            }
            if (recheckService.recheckUploaded(recheckNo)) {
                model.addAttribute("msg", "已收到您上传的压缩包，请稍后查询");
            } else {
                model.addAttribute("msg", "查重编号无效");
            }
        }
        return "query";
    }

    @RequestMapping(value = "/download")
    public String download(String recheckNo, HttpServletResponse response) {
        if (!recheckService.recheckComplete(recheckNo)) {
            return "error/404";
        }
        log.info("[结果下载]查重编号={}", recheckNo);
        String resultPath = recheckService.getResultPath() + recheckNo + "/" + recheckNo + ".xlsx";
        File file = new File(resultPath);
        // 如果文件名存在，则进行下载
        if (file.exists()) {
            // 配置文件下载
            response.setHeader("content-type", "application/octet-stream");
            response.setContentType("application/octet-stream");
            // 下载文件能正常显示中文
            response.setHeader("Content-Disposition", "attachment;filename=" + recheckNo + ".xlsx");
            // 实现文件下载
            byte[] buffer = new byte[1024];
            try (FileInputStream fis = new FileInputStream(file);
                 BufferedInputStream bis = new BufferedInputStream(fis);) {
                OutputStream os = response.getOutputStream();
                int i = bis.read(buffer);
                while (i != -1) {
                    os.write(buffer, 0, i);
                    i = bis.read(buffer);
                }
            } catch (Exception e) {
                log.error("[结果下载]下载文件出现异常，查重编号={}", recheckNo, e);
            }
            return null;
        }
        return "error/404";
    }
}
